"""
    Controller for education groups.
    Contains a lot of mass actions.
    This file is real point of interest.
"""

from datetime import date, datetime
import cherrypy
from turbogears import widgets, expose, validate, redirect, \
    validators, error_handler, identity, flash

from mnemoply import model
from mnemoply.utils import objs2ids, ids2objs, getHalfMonthBeforeToday
from mnemoply.mass_actions import registry, MassAction, MassActionForm

from mnemoply.controllers import Report
from mnemoply.controllers.lookup_new import LookupController, TableCol, TableLookupDataSource
from mnemoply.controllers.crud_new import CRUDController, RestrictController, ItemActionsTab, ItemActionsTab1, ItemTab
from mnemoply.widgets import DictionaryField, YearField, \
    MonthField, HourMinuteField, DayOfWeekField, \
    TopicField, DictField, column_widget, \
    DecimalValidator, TeacherField


class MASetEndDate(MassAction):
    target_class = model.Group
    name = "set_end_date"
    title = _("Set end date")

    def call(self, objs):
        for group in objs:
            group.calculateEndDate()


class MAChangePlan(MassAction):
    target_class = model.Group
    name = "change_plan"
    title = _("Change plan")
    form = MassActionForm(name=name,
        fields=[
            DictionaryField(
                name="plan_id",
                model_object_name='Plan',
                not_empty=True,
                label=_("Change plan"),
            ),
        ]
    )

    def call(self, objs, plan_id):
        plan = model.Plan.get(int(plan_id))

        failed = []
        for group in objs:
            for sig in model.StudentInGroup.selectBy(group=group):
                if sig.studentAgreement.initialPlan != plan:
                    failed.append((group, sig))
                    break

            if failed and failed[-1][0] != group or not failed:  # because we can't break through 2 loops
                group.replaceGroupPlan(plan)

        if failed:
            titles = ", ".join([sig.title for g, sig in failed])
            self.flash_message = _("Check the plans in contracts listeners: ") + titles

class MACreateSalaryDeduction(MassAction):
    target_class = model.Group
    name = "create_salary_deduction"
    title = _("Create salary deduction")

    form = MassActionForm(
        name=name,
        fields=[
            widgets.CalendarDatePicker(
                label=_('Start date'),
                name='start_date',
                calendar_lang='ru',
                format='%d.%m.%Y',
                validator=validators.DateTimeConverter(format="%d.%m.%Y")),
            widgets.CalendarDatePicker(
                label=_('End date'),
                name='end_date',
                calendar_lang='ru',
                format='%d.%m.%Y',
                validator=validators.DateTimeConverter(format="%d.%m.%Y")),
            ]
        )

    def createSalaryDeductions(self, group, start_date, end_date):
        if start_date > end_date:
            flash(_("Start date > end date."))
            return

        if start_date.date() < date.today() or end_date.date() < date.today():
            flash(_("Start date < today or end date < today."))
            return

        model.SalaryDeduction(group=group, teacher=group.teacher,
                              startDate=start_date, endDate=end_date)

    createSalaryDeductions.expose_object = True

    def call(self, objs, start_date, end_date):
        referer = cherrypy.request.headerMap['Referer']
        for group in objs:
            self.createSalaryDeductions(group, start_date, end_date)
        raise redirect(referer)


class MAPutSpentLessonForHimself(MassAction):
    target_class = model.Group
    name = "put_spent_lesson_for_himself"
    title = _("Put spent lesson for himself")

    def conductTeacher(self, group):
        assistant_type = model.LessonAssistantType.get(1)  # default lessons
        user = identity.current.user
        teacher = user.person
        now = datetime.today()

        if teacher is None:
            flash(_("This user is not a personal"))
            return

        if not teacher.canTeach:
            flash(_("This user is not a teacher"))
            return

        if not assistant_type.isAssistanceAvailable(group, now, teacher):
            flash(_("Today this group haven't any lesson"))
            return

        today_spent_lessons = model.SpentLesson.selectBy(date=now.date(),
                                                         group=group,
                                                         lessonAssistantType=assistant_type)

        if not today_spent_lessons.count():
            tts = [ttg.teacherTariff
                   for ttg in model.TeacherTariffGroup.selectBy(group=group)
                   if ttg.teacherTariff.lessonAssistantType == assistant_type]
            if tts:
                lesson = model.SpentLesson(date=now,
                                           group=group,
                                           teacher=teacher,
                                           numStudents=group.cacheStudents,
                                           lessonPeriod=group.lessonPeriod,
                                           teacherTariff=tts[0])

                link = ': link:%s:../SpentLesson/%d/' % (_('view'), lesson.id)
                flash(_("Spent lesson added") + link)
            else:
                flash(_("Spent lesson doesn't conducted"))
        # If today this group has spent lessons
        else:
            # If this teacher is group teacher replace all today lessons for him
            if teacher == group.teacher:
                for sl in today_spent_lessons:
                    sl.teacher = user.person
                flash(_("Spent lesson teaher changed"))
            else:
                flash(_("This connected with anoter teacher"))

    conductTeacher.expose_object = True

    def call(self, objs):
        referer = cherrypy.request.headerMap['Referer']
        for group in objs:
            self.conductTeacher(group)
        raise redirect(referer)


class MACreateDefenceAssistanceForHimself(MassAction):
    target_class = model.Group
    name = "create_defence_assistance_for_himself"
    title = _("Create defence assistance")

    def call(self, objs):
        referer = cherrypy.request.headerMap['Referer']
        assistant_type = model.LessonAssistantType.selectBy(stringId='defence_assistant')[0]
        now = date.today()
        user = identity.current.user
        if user.person is None:
            flash(_("This user is not a teacher"))
            raise redirect(referer)
        teacher = user.person

        def addLesson(group, period):
            sls = model.SpentLesson.selectBy(date=now, group=group, lessonAssistantType=assistant_type, teacher=teacher)
            if not sls.count():
                tts = [ttg.teacherTariff
                       for ttg in model.TeacherTariffGroup.selectBy(group=group)
                       if ttg.teacherTariff.lessonAssistantType == assistant_type]
                if tts:
                    model.SpentLesson(date=now,
                                      group=group,
                                      teacher=teacher,
                                      numStudents=group.cacheStudents,
                                      lessonPeriod=period,
                                      lessonAssistantType=assistant_type,
                                      teacherTariff=tts[0])
                else:
                    flash(_("Spent lesson doesn't conducted"))
            else:
                sls[0].lessonPeriod = period

        for group in objs:
            if assistant_type.isAssistanceAvailable(group, now, teacher):
                period = assistant_type.getAssistancePeriod(group, now, teacher)
                addLesson(group, period)
            else:
                flash(_("This group hasn't defences today with your assistance"))
                raise redirect(referer)


class MACreateSpentLessonFofDefaultTeacher(MassAction):
    target_class = model.Group
    name = "create_spent_lesson_for_default_teacher"
    title = _("Set teacher")

    form = MassActionForm(
        name=name,
        fields=[
            widgets.CalendarDatePicker(
                label = _('Date'),
                name = 'date',
                calendar_lang = 'ru',
                format = '%d.%m.%Y',
                validator = validators.DateTimeConverter(format="%d.%m.%Y")),
            ]
        )

    def call(self, objs, date):
        for group in objs:
            self.setTeacher(group, date.date())

    def setTeacher(self, group, date):
        if group.getLessonByDate(date):
            beginning_date, ending_date = getHalfMonthBeforeToday()
            if beginning_date < date < ending_date:
                addOrChangeSpentLesson(date, group, group.teacher)


def addOrChangeSpentLesson(date, group, teacher):
    assistant_type = model.LessonAssistantType.get(1)  # default lessons
    cur_lesson = model.SpentLesson.selectBy(date=date, group=group,
                                            lessonAssistantType=assistant_type)
    if cur_lesson.count():
        for sl in cur_lesson:
            sl.teacher = teacher
    else:
        tts = [ttg.teacherTariff
               for ttg in model.TeacherTariffGroup.selectBy(group=group)
               if ttg.teacherTariff.lessonAssistantType == assistant_type]
        if tts:
            model.SpentLesson(date=date,
                              group=group,
                              teacher=group.teacher,
                              numStudents=group.cacheStudents,
                              lessonPeriod=group.lessonPeriod,
                              teacherTariff=tts[0])
        else:
            flash(_("Spent lesson doesn't conducted"))
            raise redirect("./")


class MASetSpentLessonSubstitution(MassAction):
    target_class = model.Group
    name = "set_spent_lesson_substitution"
    title = _("Set substitution")

    form = MassActionForm(
        name=name,
        fields=[
            widgets.CalendarDatePicker(
                label = _('Date'),
                name = 'date',
                calendar_lang = 'ru',
                format = '%d.%m.%Y',
                validator = validators.DateTimeConverter(format="%d.%m.%Y")),
            ]
        )

    common_fields = [
        widgets.HiddenField(name='came_from'),
        widgets.HiddenField(name='date')
    ]

    common_form = widgets.TableForm(fields=common_fields)

    def call(self, objs, date):
        date = date.date()
        beginning_date, ending_date = getHalfMonthBeforeToday()
        came_from = cherrypy.request.headerMap['Referer']
        fields = self.common_fields[:]
        for group in objs:
            if beginning_date < date < ending_date and group.getLessonByDate(date):
                fields.append(
                    TeacherField(name="group_%d" % group.id,
                                 label=group.title))

        form = widgets.TableForm(fields=fields,
                                 action=self.getURL('set_substitution'),
                                 submit_text=_("Set substitution"))

        return dict(tg_template="genshi:mnemoply.templates.set_subs_teacher",
                    form=form,
                    came_from=came_from,
                    date=date,
                    ids=objs2ids(objs))

    @validate(form=common_form)
    @expose()
    def set_substitution(self, obj, came_from, date, **kw):
        lessons = []
        for k, v in kw.iteritems():
            if not v:
                continue
            assert k[:6] == 'group_'
            group_id = int(k[6:])
            lessons.append((model.Group.get(group_id), model.Person.get(int(v))))
            for group, teacher in lessons:
                addOrChangeSpentLesson(date, group, teacher)
        raise redirect(came_from)


class MACreateSpentLesson(MassAction):
    target_class = model.Group
    name = "create_spent_lesson"
    title = _("Create spent lessons")

    form = MassActionForm(
        name=name,
        fields=[
            widgets.CalendarDatePicker(
                label = _('Date'),
                name = 'date',
                calendar_lang = 'ru',
                format = '%d.%m.%Y',
                validator = validators.DateTimeConverter(format="%d.%m.%Y")),
            DictionaryField(
                name="teacher_id",
                model_object_name='Person',
                not_empty=True,
                label=_("Teacher"),
                records=lambda: model.Person.selectBy(canTeach=True)),
            DictionaryField(
                name="assistant_type_id",
                model_object_name='LessonAssistantType',
                not_empty=True,
                label=_("Lesson assisstant type"))
        ]
    )

    def call(self, objs, date, teacher_id, assistant_type_id):
        assistant_type = model.LessonAssistantType.get(assistant_type_id)
        teacher = model.Person.get(teacher_id)

        def addLesson(group, period):
            if not model.SpentLesson.selectBy(
                date=date, group=group,
                lessonAssistantType=assistant_type,
                teacher=teacher).count():
                tts = [ttg.teacherTariff
                       for ttg in model.TeacherTariffGroup.selectBy(group=group)
                       if ttg.teacherTariff.lessonAssistantType == assistant_type]
                if tts:
                    model.SpentLesson(date=date,
                                      group=group,
                                      teacher=teacher,
                                      numStudents=group.cacheStudents,
                                      lessonPeriod=period,
                                      lessonAssistantType=assistant_type,
                                      teacherTariff=tts[0])

        for group in objs:
            if assistant_type.isAssistanceAvailable(group, date, teacher):
                period = assistant_type.getAssistancePeriod(group, date, teacher)
                addLesson(group, period)


class MACharge(MassAction):
    target_class = model.Group
    name = "charge_payment"
    title = _("Charge payment")
    form = MassActionForm(name=name,
        fields=[
            YearField(name='year', not_empty=True, label=_("Year")),
            MonthField(name='month', not_empty=True, label=_("Month")),
        ]
    )

    def call(self, objs, month, year):
        sigs = []
        for group in objs:
            sigs += list(model.StudentInGroup.selectBy(group=group))

        return registry.getAction('StudentInGroup', 'charge_payment').call(
            sigs,
            month=month,
            year=year
        )


class MAOplataDocument(MassAction):
    target_class = model.Group
    name = "oplata_document"
    title = _("Payment document")
    form = MassActionForm(name=name,
        fields=[
            YearField(name='year', not_empty=True, label=_("Year")),
            MonthField(name='month', not_empty=True, label=_("Month")),
        ]
    )

    def call(self, objs, month, year):
        sigs = []
        for group in objs:
            sigs.extend(model.StudentInGroup.selectBy(group=group))

        return registry.getAction('StudentInGroup', 'oplata_document').call(
            sigs,
            month=month,
            year=year
        )


class MAOpenGroupDocument(MassAction):
    target_class = model.Group
    name = "open_document"
    title = _("Open group document")
    form = MassActionForm(name=name,)

    def call(self, objs):
        return Report.generate("OpenGroupDocument", ids=objs2ids(objs))


class MAStudentsList(MassAction):
    target_class = model.Group
    name = "students_list"
    title = _("Students list")
    read_only = True

    def call(self, objs):
        sigs = []
        for group in objs:
            sigs.extend(list(model.StudentInGroup.selectBy(group=group)))

        return dict(
            tg_template="genshi:mnemoply.templates.sigs_list",
            sigs=sigs,
        )


class MACalendarPlan(MassAction):
    target_class = model.Group
    name = "calendar_plan"
    title = _("Calendar plan")
    read_only = True

    def call(self, objs):
        return Report.generate('CalendarPlan', ids=objs2ids(objs))


class MAOplataDebtors(MassAction):
    target_class = model.Group
    name = "oplata_debtors"
    title = _("Debtors by payment")
    read_only = True

    def call(self, objs):
        debtors = {}

        for group in objs:
            for sig in model.StudentInGroup.selectBy(group=group):
                balance = sig.cacheBalance

                if balance < 0:
                    debtors[sig.student] = balance

        d_list = debtors.items()
        d_list.sort(key=lambda x: x[0].title)

        return dict(
            tg_template="genshi:mnemoply.templates.oplata_debtors_list",
            debtors=d_list,
        )


class MAOpenGroup(MassAction):
    target_class = model.Group
    name = "open_group"
    title = _("Open group")

    def call(self, objs):
        for group in objs:
            teacherExists = group.teacher is not None
            topicListNotEmpty = len(list(group.getGroupTopics())) > 0
            scheduleListNotEmpty = len(list(group.getSchedule())) > 0

            if teacherExists and topicListNotEmpty and scheduleListNotEmpty:
                group.isOpen = True
            else:
                self.successfully_execute = False


class MACloseGroup(MassAction):
    target_class = model.Group
    name = "close_group"
    title = _("Close group")

    def call(self, objs):
        order = model.Order.get(1) #TODO
        teacher_by_default = model.Person.get(1) #TODO
        reason = _("Group closed")
        for group in objs:

            if group.endDate > date.today():
                self.successfully_execute = False
                continue

            for sig in model.StudentInGroup.selectBy(group=group):
                close_date = group.endDate
                if close_date is None:
                    close_date = date.today()
                model.EducationHistory(student=sig.student,
                                       planAbbr=group.initialPlan.abbr,
                                       groupFrom=group,
                                       studentAgreement=sig.studentAgreement,
                                       groupTitle=group.cacheTitle,
                                       groupOpenDate=group.startDate,
                                       groupCloseDate=close_date)

                group.excludeStudent(student=sig.student,
                                     order=order,
                                     reason=reason,
                                     is_self_wish=True,
                                     comment=reason,
                                     planned=True)

            for gt in group.getGroupTopics():
                gt.destroySelf()

            for ls in group.getSchedule():
                ls.destroySelf()

            for gl in model.GroupLesson.selectBy(group=group):
                gl.destroySelf()

            group.teacher = teacher_by_default
            group.replacement1 = None
            group.replacement2 = None

            group.isOpen = False


class MARebuildPlans(MassAction):
    target_class = model.Group
    name = "rebuild_plans"
    title = _("Rebuild plans")

    def call(self, objs):
        for group in objs:
            for gt in model.GroupTopic.selectBy(group=group):
                gt.destroySelf()
            for pt in model.PlanTopic.selectBy(plan=group.initialPlan):
                model.GroupTopic(
                    group=group,
                    topic=pt.topic,
                    hours=pt.hours
                )

class LessonTab(ItemTab):
    title = _("Lessons")
    name = "lessons_tab"
    template = "../group_lessons_tab"


class ProjectDefenceTab(ItemTab):
    title = _("Project defence")
    name = "defence_tab"
    template = "../group_project_defence_tab"

    @identity.require(identity.has_any_permission('dba', 'IndividualProjectDefence/edit'))
    @expose()
    def calculate(self, obj, ids, defence_id):
        defence = model.ProjectDefence.get(int(defence_id))
        id_list = ids2objs(ids, model.IndividualProjectDefence)
        defence.calculateTimetable(id_list)
        raise redirect("./")

    add_form = widgets.TableForm(
        fields=[
            DictionaryField(
                name="teacher_id",
                model_object_name='Person',
                not_empty=True,
                label=_("Add new:"),
                records=lambda: model.Person.selectBy(canTeach=True)) ,
            widgets.HiddenField(name='defence_id')
            ],
        submit_text=_("Add"),
        action='add_defence_assistant',
        )

    @identity.require(identity.has_any_permission('dba', 'IndividualProjectDefence/edit'))
    @expose()
    def delete_individual_defence(self, obj, id_id):
        i = model.IndividualProjectDefence.get(int(id_id))
        defence = i.defence
        i.destroySelf()
        defence.recalculate()

        redirect("./")

    @identity.require(identity.has_any_permission('dba', 'ProjectDefenceAssistant/edit'))
    @validate(form=add_form)
    @expose()
    def add_defence_assistant(self, obj, teacher_id, defence_id):
        assistant = model.Person.get(int(teacher_id))
        defence = model.ProjectDefence.get(int(defence_id))
        if not model.ProjectDefenceAssistant.selectBy(
            assistant=assistant, defence=defence).count():
            model.ProjectDefenceAssistant(assistant=assistant, defence=defence)

        redirect("./")

    @identity.require(identity.has_any_permission('dba', 'ProjectDefenceAssistant/edit'))
    @expose()
    def delete_defence_assistant(self, obj, assistant_id):
        model.ProjectDefenceAssistant.get(int(assistant_id)).destroySelf()
        raise redirect("./")


class StudentsItemTab(ItemActionsTab):
    title = _("Students")
    name = "students_tab"
    ma_class_name = 'StudentInGroup'

    def getRecords(self, obj):
        sigs = list(model.StudentInGroup.selectBy(group=obj))
        sigs.sort(key=lambda x: x.title)
        return sigs


class ScheduleItemTab(ItemTab):
    title = _("Schedule")
    name = "schedule_tab"
    template = "../group_schedule_tab"

    add_form = widgets.TableForm(fields=[
        DayOfWeekField(name='day_of_week', not_empty=True, label=_("Day")),
        HourMinuteField(name='start_time', not_empty=True, label=_("Start time")),
        DictionaryField(name='classroom_id', model_object_name='Classroom',
            not_empty=True, label=_("Classroom")),
        ],
        submit_text=_("Add"),
        action='add_lis',
    )

    @identity.require(identity.has_any_permission('dba', 'LessonInSchedule/edit'))
    @validate(form=add_form)
    @expose()
    def add_lis(self, obj, day_of_week, start_time, classroom_id, tg_errors=None):
        if tg_errors:
            return self.controller.show(obj)

        classroom = model.Classroom.get(int(classroom_id))

        lis = model.LessonInSchedule(
            group=obj,
            classroom=classroom,
            startTimeHour=start_time[0],
            startTimeMinute=start_time[1],
            dayOfWeek=day_of_week,
        )

        raise redirect("./")

    @identity.require(identity.has_any_permission('dba', 'LessonInSchedule/edit'))
    @expose()
    def delete_lis(self, obj, lis_id):
        lis = model.LessonInSchedule.get(int(lis_id))
        lis.destroySelf()

        raise redirect("./")


class ScheduleChangesItemTab(ItemTab):
    title = _("Schedule changes")
    name = "schedule_changes_tab"
    template = "../group_schedule_changes_tab"

    add_form = widgets.TableForm(fields=[
        column_widget(model.GroupLesson.sqlmeta.columns.get('date')),
        DictField(name='action',
            data={0: _("Add to schedule"), 1: _("Remove from schedule")},
            not_empty=True, label=_("Action")),
        ],
        submit_text=_("Add"),
        action='add_change',
    )

    @identity.require(identity.has_any_permission('dba', 'GroupLesson/edit'))
    @validate(form=add_form)
    @expose()
    def add_change(self, obj, date, action, tg_errors=None):
        if tg_errors:
            return self.controller.show(obj)

        model.GroupLesson(group=obj, date=date, excludeLesson=bool(int(action)))

        raise redirect("./")

    @identity.require(identity.has_any_permission('dba', 'GroupLesson/edit'))
    @expose()
    def delete_change(self, obj, change_id):
        gl = model.GroupLesson.get(int(change_id))
        assert gl.group == obj

        gl.destroySelf()

        raise redirect("./")


class TeacherTariffItemTab(ItemActionsTab):
    title = _("Teacher tariff")
    name = "teacher_tariff_tab"
    obj_field = "group_id"
    model_object_child = model.TeacherTariffGroup
    field_object_main = "teacherTariff"
    template = "../group_teacher_tariff_tab"
    def get_add_form(self, obj):
        self.fields=[
                DictionaryField(
                    name='tariff_id',
                    model_object_name='TeacherTariff',
                    not_empty=True,
                    records=[t.teacherTariff for t in model.TeacherTariffPlan.selectBy(plan=obj.initialPlan)],
                    label=_("Teacher tariff")),
            ]
        add_form = widgets.TableForm(
            fields=self.fields,
            submit_text=_("Add"),
            action='add_action',
        )
        return add_form

    @expose()
    def add_action(self, obj, tariff_id):
        tariff = model.TeacherTariff.get(int(tariff_id))
        model.TeacherTariffGroup(group=obj, teacherTariff=tariff)
        raise redirect("./")


### This class is almost identical to Plan's one. Any ideas?
class TopicsItemTab(ItemTab):
    title = _("Topics")
    name = "topics_tab"
    template = "../group_topics_tab"

    add_form = widgets.TableForm(fields=[
            TopicField(
                name="topic_data",
                not_empty=True,
                label="Topic",
            ),
             widgets.TextField(
                name="hours",
                validator=DecimalValidator(not_empty=True),
                label="Hours"
            )
        ],
        submit_text=_("Add"),
        action='add_topic',
    )

    edit_form = widgets.TableForm(fields=[
            widgets.HiddenField(
                name="tid",
            ),
            widgets.HiddenField(
                name="topic_id",
            ),
            widgets.TextField(
                name="hours",
                validator=DecimalValidator(not_empty=True),
                label="Hours",
            ),
             widgets.TextField(
                name="comment",
                label="Comment",
            ),
        ],
        submit_text=_("Update"),
        action='edit_topic',
    )

    @identity.require(identity.has_any_permission('dba', 'GroupTopic/edit'))
    @expose(template="genshi:mnemoply.templates.group_topic_edit")
    def edit_topic_req(self, obj, tid):
        gtopic = model.GroupTopic.get(int(tid))
        assert gtopic.group == obj

        return dict(form=self.edit_form,
                topic=gtopic,
                values=dict(
                tid=int(tid),
                topic_id=gtopic.topic.id,
                hours=gtopic.hours,
        ))

    @identity.require(identity.has_any_permission('dba', 'GroupTopic/edit'))
    @validate(form=edit_form)
    @expose()
    def edit_topic(self, obj, tid, topic_id, hours, comment, tg_errors=None):
        gtopic = model.GroupTopic.get(int(tid))
        assert gtopic.group == obj

        if tg_errors:
            return self.edit_topic_req(obj, tid)

        gtopic.topic = model.Topic.get(int(topic_id))
        gtopic.hours = hours
        gtopic.comment = comment

        raise redirect("./")

    @identity.require(identity.has_any_permission('dba', 'GroupTopic/edit'))
    @expose()
    def delete_topic(self, obj, tid):
        tid = int(tid)
        gtopic = model.GroupTopic.get(tid)

        assert gtopic.group == obj
        ordinal = gtopic.ordinal
        group = gtopic.group
        gtopic.destroySelf()

        for topic in model.GroupTopic.selectBy(group=group):
            if topic.ordinal > ordinal:
                topic.ordinal -= 1

        raise redirect("./")

    @identity.require(identity.has_any_permission('dba', 'GroupTopic/edit'))
    @expose()
    def up_topic(self, obj, tid):
        topic = model.GroupTopic.get(int(tid))
        assert topic.group == obj
        if topic.ordinal > 1:
            prev = list(model.GroupTopic.selectBy(group=topic.group, ordinal=topic.ordinal - 1))
            if len(prev) > 0:
                prev_topic = prev[0]
                ordinal = topic.ordinal
                topic.ordinal = 0
                prev_topic.ordinal = ordinal
                topic.ordinal = ordinal - 1
            else:
                topic.ordinal -= 1

        raise redirect("./")

    @identity.require(identity.has_any_permission('dba', 'GroupTopic/edit'))
    @expose()
    def down_topic(self, obj, tid):
        topic = model.GroupTopic.get(int(tid))
        assert topic.group == obj
        max_ordinal = model.GroupTopic.selectBy(group=topic.group).max('ordinal')
        if topic.ordinal < max_ordinal:
            next = list(model.GroupTopic.selectBy(group=topic.group, ordinal=topic.ordinal + 1))
            if len(next) > 0:
                next_topic = next[0]
                ordinal = topic.ordinal
                topic.ordinal = 0
                next_topic.ordinal = ordinal
                topic.ordinal = ordinal + 1
            else:
                topic.ordinal += 1

        raise redirect("./")

    @expose()
    def index(self):
        raise redirect("./")

    @identity.require(identity.has_any_permission('dba', 'GroupTopic/edit'))
    @expose()
    @validate(form=add_form)
    @error_handler(index)
    def add_topic(self, obj, topic_data, hours):
        if topic_data is not None:
            topic = model.Topic.get(int(topic_data))
            model.GroupTopic(group=obj, topic=topic, hours=hours)

        raise redirect("./")


class GroupController(CRUDController):
    lookup_columns = [
        TableCol(name='plan_id', caption='', size=1, hide=True),
        TableCol(name='faculty', caption=_("Faculty")),
        TableCol(name='title', caption=_("Name"), size=14),
        TableCol(name='education_type', caption=_("Initial plan")),
        TableCol(name='teacher', caption=_("Teacher"), size=13),
        TableCol(name='students_left', caption=_("Seats left"), size=4, validator=validators.Int()),
        TableCol(name='year', caption=_("Year"), size=4),
        TableCol(name='office', caption=_("Office"), size=10, hidden=True),
        TableCol(name='max_students', caption=_("Max students"), size=4, hidden=True,
            validator=validators.Int()),
        TableCol(name='cache_students', caption=_("Number of students"), size=4, hidden=True,
            validator=validators.Int()),
        TableCol(name='cache_schedule_days', caption=_("Schedule days"), hidden=True),
        TableCol(name='start_date', caption=_("Start date"), hidden=True),
        TableCol(name='end_date', caption=_("End date"), hidden=True),
        TableCol(name='is_open_str', caption=_("State"), hidden=True),
        TableCol(name='with_agreement', caption=_("With agreement"), hidden=True),
        TableCol(name='session', caption=_("Session"), hidden=True),
        TableCol(name='replacement1', caption=_("Replacement 1"), hidden=True),
        TableCol(name='replacement2', caption=_("Replacement 2"), hidden=True),
        TableCol(name='comment', caption=_("Comment"), hidden=True),
    ]
    model_object = model.Group
    item_tabs = [
        StudentsItemTab(), ScheduleItemTab(),
        TopicsItemTab(), ScheduleChangesItemTab(),
        LessonTab(), ProjectDefenceTab(),
        TeacherTariffItemTab(),
        ]
    add_fields = [
        'officeID',
        'initialPlanID',
        'organizationID',
        'customerTariffID',
        'teacherID', 'replacement1ID', 'replacement2ID',
        'maxStudents', 'lessonPeriod',
        'startDate',
        'comment',
        'withAgreement',
        'session',
    ]
    edit_fields = ['ordinal'] + add_fields
    view_fields = edit_fields + ['endDate', 'isOpen']
    edit_fields.remove('initialPlanID')  # hack: remove group.plan from edit fields
    mysql_view_name = 'group_lookup'

    #def fill_lookup_data_defaults(self, data):
    #    is_parent_filled = LookupControllerBase.fill_lookup_data_defaults(self, data)
    #    if not is_parent_filled:
    #        office = identity.current.user.office.name
    #        args = {'flt_office': office,
    #                'column': ['title', 'education_type', 'teacher', 'students_left', 'office']}
    #        data.update(args)

exposed = GroupController()